package com.demon.activitychange;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;

import com.demon.activitychange.net.Callback;
import com.demon.activitychange.net.IApiMgr;
import com.demon.activitychange.net.impl.ApiMgrFactory;
import com.demon.activitychange.net.impl.IWebSocketRecv;
import com.demon.activitychange.net.impl.WebSocketMgr;
import com.demon.activitychange.persist.IPersist;
import com.demon.activitychange.persist.PersistKey;
import com.demon.activitychange.persist.impl.FilePersist;
import com.demon.activitychange.persist.impl.PersistFactory;
import com.demon.activitychange.util.JSONObjectPack;
import com.demon.activitychange.util.LaunchUtil;
import com.demon.activitychange.util.ShellUtils;
import com.demon.activitychange.util.TraceUtil;
import com.demon.activitychange.util.UniqueCodeUtil;
import com.demon.activitychange.xposed.HookMain.DyOperEnum;
import com.demon.activitychange.xposed.HookMain;
import com.umeng.cconfig.UMRemoteConfig;
import com.xy.vpnsdk.xyOpenSdk;
import com.xy.vpnsdk.xyState;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;

public class MainActivity extends AppCompatActivity implements View.OnClickListener, IWebSocketRecv, CompoundButton.OnCheckedChangeListener {
    private Context mContext = this;
    private EditText mEditDomain;
    private EditText mEditAccount;
    private EditText mEditPass;
    private Button mBtnSave;
    private Button mBtnCache;
    private Button mBtnStart;
    private Button mBtnStop;
    private Switch mSwVpn;
    private Switch mSwDy;
    private TextView mTxtDevice;
    private TextView mTxtDeviceName;
    private TextView mTxtVer;
    private TextView mTxtState;
    private IPersist mPersistence;
    private String mDeviceName, mDeviceId;
    private Handler mainHandler = new Handler(Looper.getMainLooper());
    private IApiMgr mApiMgr;

    public static String PACKAGE_ID;
    private boolean isLiteDy = false;
    private boolean isUseVpn = false;
    private boolean isUpdateIP = false;
    private String loginData = "", sendCodeData = "", messageData;
    private xyState.StateListener stateListener = new xyState.StateListener() {
        @Override
        public void errorBack(final int state, final String s) {
            TraceUtil.e("error:" + state + " des:" + s);
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    mTxtState.setText("雷电状态：" + state + "，" + s);
                }
            });

            // -5: 用户校验失败
            //  5: 连接超时，退出
            // -6: 没有获取到可用配置
            if (state == -5 || state == 5 || state == -6) {
                onUpdateIpError(s);
            }
        }

        @Override
        public void updateState(final int state, final String s) {
            TraceUtil.e("state:" + state + " des:" + s);
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    mTxtState.setText("雷电状态：" + state + "，" + s);
                }
            });

            if (state == 2 && isUpdateIP) {
                onUpdateIpSuccess();
            }
            // -5: 用户校验失败
            //  5: 连接超时，退出
            // -6: 没有获取到可用配置
            else if (state == -5 || state == 5 || state == -6) {
                onUpdateIpError(s);
            }
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEditDomain = findViewById(R.id.edit_domain);
        mEditAccount = findViewById(R.id.edit_account);
        mEditPass = findViewById(R.id.edit_password);
        mBtnSave = findViewById(R.id.btn_save);
        mBtnCache = findViewById(R.id.btn_cache);
        mBtnStart = findViewById(R.id.btn_start);
        mBtnStop = findViewById(R.id.btn_stop);
        mSwVpn = findViewById(R.id.switch_vpn);
        mSwDy = findViewById(R.id.switch_dy);
        mTxtDevice = findViewById(R.id.tv_device);
        mTxtDeviceName = findViewById(R.id.tv_deviceName);
        mTxtVer = findViewById(R.id.tv_version);
        mTxtState = findViewById(R.id.tv_state);
        mBtnSave.setOnClickListener(this);
        mBtnCache.setOnClickListener(this);
        mBtnStart.setOnClickListener(this);
        mBtnStop.setOnClickListener(this);
        mSwVpn.setOnCheckedChangeListener(this);
        mSwDy.setOnCheckedChangeListener(this);
        mPersistence = PersistFactory.getInstance(this);
        mApiMgr = ApiMgrFactory.getInstance(mContext);

        try {
            PackageInfo packInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
            ApplicationInfo appInfo = mContext.getApplicationInfo();
            setTitle(mContext.getResources().getString(appInfo.labelRes) + packInfo.versionName);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

        mEditAccount.setText((String) mPersistence.readData(PersistKey.LEIDIAN_ACCOUNT, ""));
        mEditPass.setText((String) mPersistence.readData(PersistKey.LEIDIAN_PASSWORD, ""));
        isUseVpn = (boolean) mPersistence.readData(PersistKey.VPN_STATE, false);
        isLiteDy = (boolean) mPersistence.readData(PersistKey.LITE_STATE, false);
        setPackageId(isLiteDy);
        mSwVpn.setChecked(isUseVpn);
        mSwDy.setChecked(isLiteDy);
        String domain = (String) mPersistence.readData(PersistKey.DOMAIN, "");
        if (TextUtils.isEmpty(domain)) {
            domain = "139.9.105.162";
            mPersistence.writeData(PersistKey.DOMAIN, domain);
        }
        mEditDomain.setText(domain);

        String wsAccount = isLiteDy ? "lite" : "norm";
        WebSocketMgr.getInstance().openWebSocket(domain, wsAccount, MainActivity.this);

        mDeviceName = UniqueCodeUtil.getDeviceBrand() + " " + UniqueCodeUtil.getDeviceModel();
        mDeviceId = UniqueCodeUtil.getIMEI(this);
        mTxtDeviceName.setText("设备名：" + mDeviceName);
        mTxtDevice.setText("设备id：" + mDeviceId);
        mTxtVer.setText("雷电Ver：" + xyOpenSdk.getInstance().getVersionName());
        registerBroadcast();
        xyOpenSdk.getInstance().addStateListener(stateListener);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        WebSocketMgr.getInstance().closeWebSocketNoReconnect();
        unRegisterBroadcst();
        stopProxy();
        xyOpenSdk.getInstance().removeSateListener(stateListener);
    }

    @Override
    public void onClick(View v) {
        if (!ShellUtils.isRoot()) {
            Toast.makeText(mContext, "APP需要root权限，请打开root权限！", Toast.LENGTH_SHORT).show();
            return;
        }

        int resId = v.getId();
        if (resId == R.id.btn_save) {
            String domain = mEditDomain.getText().toString().trim();
            String account = mEditAccount.getText().toString().trim();
            String password = mEditPass.getText().toString().trim();
            if (TextUtils.isEmpty(domain)) {
                Toast.makeText(mContext, "ip不能为空", Toast.LENGTH_SHORT).show();
                return;
            } else if (TextUtils.isEmpty(account)) {
                Toast.makeText(mContext, "账号不能为空", Toast.LENGTH_SHORT).show();
                return;
            } else if (TextUtils.isEmpty(password)) {
                Toast.makeText(mContext, "密码不能为空", Toast.LENGTH_SHORT).show();
                return;
            }
            mPersistence.writeData(PersistKey.DOMAIN, domain);
            mPersistence.writeData(PersistKey.LEIDIAN_ACCOUNT, account);
            mPersistence.writeData(PersistKey.LEIDIAN_PASSWORD, password);
            Toast.makeText(mContext, "设置生效，需要重启APP！", Toast.LENGTH_SHORT).show();
        } else if (resId == R.id.btn_start) {
            updateIP("");
        } else if (resId == R.id.btn_stop) {
            stopProxy();
            WebSocketMgr.getInstance().restartWebSocket((String) mPersistence.readData(PersistKey.DOMAIN, ""), isLiteDy ? "lite" : "norm", MainActivity.this);
        } else if (resId == R.id.btn_cache) {
            String phone = (String) FilePersist.newInstance(PACKAGE_ID).readData("phone", "");
            if (!TextUtils.isEmpty(phone)) {
                ClearExitAppThread.saveApp(phone);
            } else {
                TraceUtil.e("****** dy save app error, phone is null ******");
            }
        }
    }

    @Override
    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
        int id = buttonView.getId();
        switch (id) {
            case R.id.switch_vpn:
                isUseVpn = isChecked;
                mPersistence.writeData(PersistKey.VPN_STATE, isChecked);
                break;
            case R.id.switch_dy:
                isLiteDy = isChecked;
                setPackageId(isLiteDy);
                mPersistence.writeData(PersistKey.LITE_STATE, isChecked);
                WebSocketMgr.getInstance().restartWebSocket((String) mPersistence.readData(PersistKey.DOMAIN, ""), isLiteDy ? "lite" : "norm", MainActivity.this);
                break;
            default:
                break;
        }
    }

    @Override
    public void recvCmd(String cmd, final String data) {
        String canUser = UMRemoteConfig.getInstance().getConfigValue("canUse");
        TraceUtil.e("canUse: " + canUser);
        if ("false".equals(canUser)) {
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(mContext, "君子坦荡荡，小人长戚戚！", Toast.LENGTH_SHORT).show();
                }
            });
            return;
        }

        JSONObject jsObj = new JSONObject();
        try {
            jsObj = new JSONObject(data);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        TraceUtil.e("recvCmd: cmd = " + cmd + ", data = " + data);
        if (DyOperEnum.login.toString().equals(cmd)) {
            String phone = jsObj.optString("phone");
            JSONObject phoneInfo = jsObj.optJSONObject("phoneInfo");
            TraceUtil.e("phoneInfo = " + phoneInfo);
            FilePersist.newInstance(PACKAGE_ID).writeData("phone", phone);
            if (jsObj.has("device") && !TextUtils.isEmpty(jsObj.optString("device"))) {
                FilePersist.newInstance(PACKAGE_ID).writeData("device", jsObj.optString("device"));
            } else {
                FilePersist.newInstance(PACKAGE_ID).writeData("device", "8612");
            }

            if (isUseVpn) {
                loginData = data;
                String province = phoneInfo == null ? "" : phoneInfo.optString("province");
                updateIP(province);
            } else {
                new ClearExitAppThread(mContext, mainHandler, new Callback() {
                    @Override
                    public void onSuccess(Object callData) {
                        LaunchUtil.startApp(mContext, PACKAGE_ID, DyOperEnum.login.toString(), data);
                    }

                    @Override
                    public void onFailure(String error) {
                        JSONObject obj = new JSONObjectPack()
                                .putValue("code", 1)
                                .putValue("data", "")
                                .putValue("msg", error)
                                .getJSONObject();
                        mApiMgr.uploadResult(DyOperEnum.login.toString(), obj, null);
                    }
                }).start();
            }
        } else if (DyOperEnum.loginVerify.toString().equals(cmd)) {
            Intent intent = new Intent(DyOperEnum.loginVerify.getBroadcast());
            intent.putExtra("code", jsObj.optString("code"));
            mContext.sendBroadcast(intent);
        } else if (DyOperEnum.sendCode.toString().equals(cmd)) {
            String phone = jsObj.optString("phone");
            JSONObject phoneInfo = jsObj.optJSONObject("phoneInfo");
            TraceUtil.e("phoneInfo = " + phoneInfo);
            FilePersist.newInstance(PACKAGE_ID).writeData("phone", phone);
            if (jsObj.has("device") && !TextUtils.isEmpty(jsObj.optString("device"))) {
                FilePersist.newInstance(PACKAGE_ID).writeData("device", jsObj.optString("device"));
            } else {
                FilePersist.newInstance(PACKAGE_ID).writeData("device", "8612");
            }

            if (isUseVpn) {
                sendCodeData = data;
                String province = phoneInfo == null ? "" : phoneInfo.optString("province");
                updateIP(province);
            } else {
                new ClearExitAppThread(mContext, mainHandler, new Callback() {
                    @Override
                    public void onSuccess(Object callData) {
                        LaunchUtil.startApp(mContext, PACKAGE_ID, DyOperEnum.sendCode.toString(), data);
                    }

                    @Override
                    public void onFailure(String error) {
                        JSONObject obj = new JSONObjectPack()
                                .putValue("code", 1)
                                .putValue("data", "")
                                .putValue("msg", error)
                                .getJSONObject();
                        mApiMgr.uploadResult(DyOperEnum.sendCode.toString(), obj, null);
                    }
                }).start();
            }
        } else if (DyOperEnum.smsLogin.toString().equals(cmd)) {
            Intent intent = new Intent(DyOperEnum.smsLogin.getBroadcast());
            intent.putExtra("code", jsObj.optString("code"));
            mContext.sendBroadcast(intent);
        } else if (DyOperEnum.smsReg.toString().equals(cmd)) {
            Intent intent = new Intent(DyOperEnum.smsReg.getBroadcast());
            intent.putExtra("password", jsObj.optString("password"));
            intent.putExtra("code", jsObj.optString("code"));
            mContext.sendBroadcast(intent);
        } else if (DyOperEnum.smsUpdatePassword.toString().equals(cmd)) {
            Intent intent = new Intent(DyOperEnum.smsUpdatePassword.getBroadcast());
            intent.putExtra("code", jsObj.optString("code"));
            mContext.sendBroadcast(intent);
        } else if (DyOperEnum.exit.toString().equals(cmd)) {
            boolean isRunning = ShellUtils.isAppRunning(PACKAGE_ID);
            if (isRunning) {
                TraceUtil.e("app is running");
                Intent intent = new Intent(DyOperEnum.exit.getBroadcast());
                mContext.sendBroadcast(intent);
                sendExitResult();
            } else {
                TraceUtil.e("app is close");
                ClearExitAppThread.clearApp();
                sendExitResult();
            }
            stopProxy();
            WebSocketMgr.getInstance().restartWebSocket((String) mPersistence.readData(PersistKey.DOMAIN, ""), isLiteDy ? "lite" : "norm", MainActivity.this);
        } else if (DyOperEnum.message.toString().equals(cmd)) {
            String phone = jsObj.optString("phone");
            JSONObject phoneInfo = jsObj.optJSONObject("phoneInfo");
            TraceUtil.e("phoneInfo = " + phoneInfo);
            FilePersist.newInstance(PACKAGE_ID).writeData("phone", phone);
            if (jsObj.has("device") && !TextUtils.isEmpty(jsObj.optString("device"))) {
                FilePersist.newInstance(PACKAGE_ID).writeData("device", jsObj.optString("device"));
            } else {
                FilePersist.newInstance(PACKAGE_ID).writeData("device", "8612");
            }

            if (isUseVpn) {
                messageData = data;
                String province = phoneInfo == null ? "" : phoneInfo.optString("province");
                updateIP(province);
            } else {
                new ClearExitAppThread(mContext, mainHandler, new Callback() {
                    @Override
                    public void onSuccess(Object callData) {
                        if (ClearExitAppThread.hasCache(phone)) {
                            TraceUtil.e(phone + " 存在缓存！");
                            ClearExitAppThread.restoreApp(phone);
                        } else {
                            TraceUtil.e(phone + " 没有缓存！");
                        }
                        LaunchUtil.startApp(mContext, PACKAGE_ID, DyOperEnum.message.toString(), data);
                    }

                    @Override
                    public void onFailure(String error) {
                        JSONObject obj = new JSONObjectPack()
                                .putValue("code", 1)
                                .putValue("data", "")
                                .putValue("msg", error)
                                .getJSONObject();
                        mApiMgr.uploadResult(DyOperEnum.message.toString(), obj, null);
                    }
                }).start();
            }
        }
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(final Context context, final Intent intent) {
            String action = intent.getAction();
            TraceUtil.e("receive broadcast action " + action);
            JSONObject obj = new JSONObjectPack()
                    .putValue("code", 1)
                    .putValue("data", "")
                    .putValue("msg", "结果解析异常")
                    .getJSONObject();

            String data = intent.getStringExtra("data");
            try {
                if (!TextUtils.isEmpty(data)) {
                    obj = new JSONObject(data);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
            if (DyOperEnum.login.getResult().equals(action)) {
                mApiMgr.uploadResult(DyOperEnum.login.toString(), obj, null);
            } else if (DyOperEnum.loginVerify.getResult().equals(action)) {
                mApiMgr.uploadResult(DyOperEnum.loginVerify.toString(), obj, null);
            } else if (DyOperEnum.sendCode.getResult().equals(action)) {
                mApiMgr.uploadResult(DyOperEnum.sendCode.toString(), obj, null);
            } else if (DyOperEnum.smsLogin.getResult().equals(action)) {
                mApiMgr.uploadResult(DyOperEnum.smsLogin.toString(), obj, null);
            } else if (DyOperEnum.smsReg.getResult().equals(action)) {
                mApiMgr.uploadResult(DyOperEnum.smsReg.toString(), obj, null);
            } else if (DyOperEnum.smsUpdatePassword.getResult().equals(action)) {
                mApiMgr.uploadResult(DyOperEnum.smsUpdatePassword.toString(), obj, null);
            } else if (DyOperEnum.message.getResult().equals(action)) {
                mApiMgr.uploadResult(DyOperEnum.message.toString(), obj, null);
                if (obj.optInt("code") == 0) {
                    String phone = (String) FilePersist.newInstance(PACKAGE_ID).readData("phone", "");
                    if (!TextUtils.isEmpty(phone)) {
                        ClearExitAppThread.saveApp(phone);
                    }
                }
            } else if (DyOperEnum.exit.getResult().equals(action)) {
                stopProxy();
                WebSocketMgr.getInstance().restartWebSocket((String) mPersistence.readData(PersistKey.DOMAIN, ""), isLiteDy ? "lite" : "norm", MainActivity.this);
            } else if ("dy.save.app".equals(action)) {
                String phone = (String) FilePersist.newInstance(PACKAGE_ID).readData("phone", "");
                if (!TextUtils.isEmpty(phone)) {
                    ClearExitAppThread.saveApp(phone);
                }
            } else if ("dy.restore.app".equals(action)) {
                ClearExitAppThread.restoreApp(intent.getStringExtra("phone"));
            }
        }
    };

    private void registerBroadcast() {
        IntentFilter filter = new IntentFilter();
        filter.addAction(DyOperEnum.login.getResult());
        filter.addAction(DyOperEnum.loginVerify.getResult());
        filter.addAction(DyOperEnum.sendCode.getResult());
        filter.addAction(DyOperEnum.smsLogin.getResult());
        filter.addAction(DyOperEnum.smsReg.getResult());
        filter.addAction(DyOperEnum.smsUpdatePassword.getResult());
        filter.addAction(DyOperEnum.message.getResult());
        filter.addAction(DyOperEnum.exit.getResult());
        filter.addAction("dy.save.app");
        filter.addAction("dy.restore.app");
        mContext.registerReceiver(mReceiver, filter);
    }

    private void unRegisterBroadcst() {
        mContext.unregisterReceiver(mReceiver);
    }

    private void sendExitResult() {
        JSONObject obj = new JSONObjectPack()
                .putValue("code", 0)
                .putValue("data", "")
                .putValue("msg", "")
                .getJSONObject();
        mApiMgr.uploadResult(DyOperEnum.exit.toString(), obj, null);
    }

    private void updateIP(String province) {
        if (isUseVpn) {
            stopProxy();
            WebSocketMgr.getInstance().closeWebSocketNoReconnect();
            isUpdateIP = true;
            mainHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    TraceUtil.e("打开代理，切换ip！");
                    if (!TextUtils.isEmpty(province)) {
                        String dealPro = dealProvince(province);
                        String city = "";
                        xyOpenSdk.getInstance().startProxy(MainActivity.this, dealPro, city);
                    } else {
                        xyOpenSdk.getInstance().startProxy(MainActivity.this);
                    }

                }
            }, 3500);
        }
    }

    private void stopProxy() {
        if (isUseVpn) {
            TraceUtil.e("关闭代理！");
            mainHandler.post(new Runnable() {
                @Override
                public void run() {
                    mTxtState.setText("雷电状态：关闭代理");
                }
            });
            xyOpenSdk.getInstance().stopProxy(MainActivity.this);
        }
    }

    private void onUpdateIpSuccess() {
        isUpdateIP = false;
        mainHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                String domain = (String) mPersistence.readData(PersistKey.DOMAIN, "");
                String wsAccount = isLiteDy ? "lite" : "norm";
                WebSocketMgr.getInstance().openWebSocket(domain, wsAccount, MainActivity.this);
                if (!TextUtils.isEmpty(loginData)) {
                    final String fLoginData = loginData;
                    new ClearExitAppThread(mContext, mainHandler, new Callback() {
                        @Override
                        public void onSuccess(Object callData) {
                            LaunchUtil.startApp(mContext, PACKAGE_ID, DyOperEnum.login.toString(), fLoginData);
                        }

                        @Override
                        public void onFailure(String error) {
                            JSONObject obj = new JSONObjectPack()
                                    .putValue("code", 1)
                                    .putValue("data", "")
                                    .putValue("msg", error)
                                    .getJSONObject();
                            mApiMgr.uploadResult(DyOperEnum.login.toString(), obj, null);
                        }
                    }).start();
                    loginData = "";
                } else if (!TextUtils.isEmpty(sendCodeData)) {
                    final String fSendCodeData = sendCodeData;
                    new ClearExitAppThread(mContext, mainHandler, new Callback() {
                        @Override
                        public void onSuccess(Object callData) {
                            LaunchUtil.startApp(mContext, PACKAGE_ID, DyOperEnum.sendCode.toString(), fSendCodeData);
                        }

                        @Override
                        public void onFailure(String error) {
                            JSONObject obj = new JSONObjectPack()
                                    .putValue("code", 1)
                                    .putValue("data", "")
                                    .putValue("msg", error)
                                    .getJSONObject();
                            mApiMgr.uploadResult(DyOperEnum.sendCode.toString(), obj, null);
                        }
                    }).start();
                    sendCodeData = "";
                } else if (!TextUtils.isEmpty(messageData)) {
                    final String fMessageData = messageData;
                    new ClearExitAppThread(mContext, mainHandler, new Callback() {
                        @Override
                        public void onSuccess(Object callData) {
                            try {
                                JSONObject jsObj = new JSONObject(fMessageData);
                                String phone = jsObj.optString("phone");
                                if (ClearExitAppThread.hasCache(phone)) {
                                    TraceUtil.e(phone + " 存在缓存！");
                                    ClearExitAppThread.restoreApp(phone);
                                } else {
                                    TraceUtil.e(phone + " 没有缓存！");
                                }
                            } catch (JSONException e) {
                                e.printStackTrace();
                            }
                            LaunchUtil.startApp(mContext, PACKAGE_ID, DyOperEnum.message.toString(), fMessageData);
                        }

                        @Override
                        public void onFailure(String error) {
                            JSONObject obj = new JSONObjectPack()
                                    .putValue("code", 1)
                                    .putValue("data", "")
                                    .putValue("msg", error)
                                    .getJSONObject();
                            mApiMgr.uploadResult(DyOperEnum.message.toString(), obj, null);
                        }
                    }).start();
                    messageData = "";
                }
            }
        }, 1000);
    }

    private void onUpdateIpError(String err) {
        stopProxy();
        String domain = (String) mPersistence.readData(PersistKey.DOMAIN, "");
        String wsAccount = isLiteDy ? "lite" : "norm";
        WebSocketMgr.getInstance().openWebSocket(domain, wsAccount, MainActivity.this);
        JSONObject obj = new JSONObjectPack()
                .putValue("code", 1)
                .putValue("data", "")
                .putValue("msg", "vpn异常：" + err)
                .getJSONObject();
        if (!TextUtils.isEmpty(loginData)) {
            loginData = "";
            mApiMgr.uploadResult(DyOperEnum.login.toString(), obj, null);
        } else if (!TextUtils.isEmpty(sendCodeData)) {
            sendCodeData = "";
            mApiMgr.uploadResult(DyOperEnum.sendCode.toString(), obj, null);
        } else if (!TextUtils.isEmpty(messageData)) {
            messageData = "";
            mApiMgr.uploadResult(DyOperEnum.message.toString(), obj, null);
        }
    }

    private String dealProvince(String province) {
        if ("北京".equals(province) || "天津".equals(province) || "上海".equals(province) || "重庆".equals(province)) {
            return province + "市";
        }
        return province + "省";
    }

    private void setPackageId(boolean isLite) {
        if (isLiteDy) {
            PACKAGE_ID = HookMain.PACKAGE_ID_LITE;
        } else {
            PACKAGE_ID = HookMain.PACKAGE_ID_NORM;
        }
    }
}

class ClearExitAppThread extends Thread {
    private boolean isRunning;
    private Context context;
    private Callback callback;
    private Handler mHandler;
    private int mCnt;

    public ClearExitAppThread(Context context, Handler handler, Callback callback) {
        super();
        this.context = context;
        this.mHandler = handler;
        this.callback = callback;
        this.mCnt = 0;
    }

    @Override
    public void run() {
        super.run();
        isRunning = ShellUtils.isAppRunning(MainActivity.PACKAGE_ID);
        do {
            if (isRunning) {
                TraceUtil.e("app is running");
                Intent intent = new Intent(DyOperEnum.exit.getBroadcast());
                this.context.sendBroadcast(intent);
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                isRunning = ShellUtils.isAppRunning(MainActivity.PACKAGE_ID);
                if (isRunning) {
                    TraceUtil.e("app强制关闭中");
                    ShellUtils.exitApp(MainActivity.PACKAGE_ID);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    isRunning = false;
                }
            } else {
                TraceUtil.e("app is close");
                clearApp();
            }
            if (!isRunning) {
                onSuccess();
            }
        } while (this.isRunning);
    }

    private void onSuccess() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.onSuccess("");
            }
        });
    }

    private void onError(final String str) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                callback.onFailure(str);
            }
        });
    }

    public static synchronized void clearApp() {
        TraceUtil.e("****** dy clear app start ******");
        String baseInner = "/data/user/0/" + MainActivity.PACKAGE_ID + "/";
        String baseExternal = "/storage/emulated/0/Android/data/" + MainActivity.PACKAGE_ID + "/";

        // 删除SharedPreferences 账户信息
        File file = new File(baseInner + "shared_prefs/aweme_user.xml");
        ShellUtils.deleteFile(file);
        // 删除SharedPreferences cdid信息
        file = new File(baseInner + "shared_prefs/com.ss.android.deviceregister.utils.Cdid.xml");
        ShellUtils.deleteFile(file);
        // 删除SharedPreferences udid、udid_list、openudid、clientudid、serial_number信息
        file = new File(baseInner + "shared_prefs/snssdk_openudid.xml");
        ShellUtils.deleteFile(file);
        // 删除SharedPreferences device_id信息
        file = new File(baseInner + "shared_prefs/applog_stats.xml");
        ShellUtils.deleteFile(file);
        // 删除SharedPreferences cookies缓存
        file = new File(baseInner + "shared_prefs/ttnetCookieStore.xml");
        ShellUtils.deleteFile(file);

        // 删除Files 下的device信息
        file = new File(baseInner + "files/keva/repo/");
        ShellUtils.deleteFile(file);
        TraceUtil.e("keva/repo 文件夹已清空！");
        // 删除APP_WEBVIEW下cookies缓存
        file = new File(baseInner + "app_webview/Cookies");
        ShellUtils.deleteFile(file);

        // 删除contentProvider device_id信息
        file = new File(baseExternal + "bytedance/device_parameters.dat");
        ShellUtils.deleteFile(file);

//        // 删除com.snssdk.api device_id信息
//        file = new File(baseExternal + "bytedance/device_parameters.dat");
//        String snssdkPath = file.getAbsolutePath().replace(MainActivity.PACKAGE_ID, "com.snssdk.api");
//        file = new File(snssdkPath);
//        ShellUtils.deleteFile(file);
//
//        // 删除sdcard device_id信息
//        file = new File("/storage/emulated/0/bytedance/device_parameters.dat");
//        ShellUtils.deleteFile(file);

        TraceUtil.e("****** dy clear app end ******");
    }

    public static synchronized boolean hasCache(String phone) {
        TraceUtil.e("****** dy cache ******");
        String baseInnerDir = "/data/user/0/com.dy.backup/" + phone + "/";
        File file = new File(baseInnerDir + "aweme_user.xml");
        boolean success = ShellUtils.exists(file);
        if (!success) {
            return false;
        }

        file = new File(baseInnerDir + "applog_stats.xml");
        success = ShellUtils.exists(file);
        if (!success) {
            return false;
        }

        file = new File(baseInnerDir + "Cookies");
        success = ShellUtils.exists(file);
        if (!success) {
            return false;
        }

        return true;
    }

    public static synchronized void saveApp(String phone) {
        TraceUtil.e("****** dy save app start ******");
        String baseInner = "/data/user/0/" + MainActivity.PACKAGE_ID + "/";
        String baseExternal = "/storage/emulated/0/Android/data/" + MainActivity.PACKAGE_ID + "/";

        // 创建app信息存储目录
        File baseInnerDir = new File("/data/user/0/com.dy.backup/" + phone);
        File baseExternalDir = new File("/storage/emulated/0/Android/data/com.dy.backup/" + phone);
        ShellUtils.createDir(baseInnerDir);
        ShellUtils.createDir(baseExternalDir);

        // 移动SharedPreferences 账户信息
        File file = new File(baseInner + "shared_prefs/aweme_user.xml");
        ShellUtils.moveFile(file, baseInnerDir);
        // 移动SharedPreferences cdid信息
        file = new File(baseInner + "shared_prefs/com.ss.android.deviceregister.utils.Cdid.xml");
        ShellUtils.moveFile(file, baseInnerDir);
        // 移动SharedPreferences udid、udid_list、openudid、clientudid、serial_number信息
        file = new File(baseInner + "shared_prefs/snssdk_openudid.xml");
        ShellUtils.moveFile(file, baseInnerDir);
        // 移动SharedPreferences device_id信息
        file = new File(baseInner + "shared_prefs/applog_stats.xml");
        ShellUtils.moveFile(file, baseInnerDir);
        // 移动SharedPreferences cookies缓存
        file = new File(baseInner + "shared_prefs/ttnetCookieStore.xml");
        ShellUtils.moveFile(file, baseInnerDir);

        // 移动Files 下的device信息
        file = new File(baseInner + "files/keva/repo/");
        ShellUtils.moveFile(file, baseInnerDir);

        // 移动APP_WEBVIEW下cookies缓存
        file = new File(baseInner + "app_webview/Cookies");
        ShellUtils.moveFile(file, baseInnerDir);

        // 移动contentProvider device_id信息
        file = new File(baseExternal + "bytedance/device_parameters.dat");
        ShellUtils.moveFile(file, baseExternalDir);
        file = new File(baseExternal + "bytedance/persist_data.txt");
        ShellUtils.moveFile(file, baseExternalDir);

        TraceUtil.e("****** dy save app end ******");
    }

    public static synchronized void restoreApp(String phone) {
        TraceUtil.e("****** dy restore app start ******");
        String baseInner = "", baseExternal = "";
        String baseInnerDir = "/data/user/0/" + MainActivity.PACKAGE_ID + "/";
        String baseExternalDir = "/storage/emulated/0/Android/data/" + MainActivity.PACKAGE_ID + "/";

        // 创建app信息存储目录
        File file = new File("/data/user/0/com.dy.backup/" + phone);
        if (!ShellUtils.exists(file)) {
            TraceUtil.e("baseInner: " + file.getName() + " 文件不存在！");
            return;
        } else {
            baseInner = file.getAbsolutePath() + "/";
        }
        file = new File("/storage/emulated/0/Android/data/com.dy.backup/" + phone);
        if (!ShellUtils.exists(file)) {
            TraceUtil.e("baseExternal: " + file.getName() + " 文件不存在！");
            return;
        } else {
            baseExternal = file.getAbsolutePath() + "/";
        }

        boolean isCloseSELinux = ShellUtils.closeSELinux();
        if (isCloseSELinux) {
            // 恢复SharedPreferences 账户信息
            File dir = new File(baseInnerDir + "shared_prefs");
            file = new File(baseInner + "aweme_user.xml");
            ShellUtils.copyFileAndCtx(file, dir);
            // 恢复SharedPreferences cdid信息
            file = new File(baseInner + "com.ss.android.deviceregister.utils.Cdid.xml");
            ShellUtils.copyFileAndCtx(file, dir);
            // 恢复SharedPreferences udid、udid_list、openudid、clientudid、serial_number信息
            file = new File(baseInner + "snssdk_openudid.xml");
            ShellUtils.copyFileAndCtx(file, dir);
            // 恢复SharedPreferences device_id信息
            file = new File(baseInner + "applog_stats.xml");
            ShellUtils.copyFileAndCtx(file, dir);
            // 恢复SharedPreferences cookies缓存
            file = new File(baseInner + "ttnetCookieStore.xml");
            ShellUtils.copyFileAndCtx(file, dir);

            // 恢复Files 下的device信息
            dir = new File(baseInnerDir + "files/keva/");
            file = new File(baseInner + "repo");
            ShellUtils.copyFileAndCtx(file, dir);
            // 恢复APP_WEBVIEW下cookies缓存
            dir = new File(baseInnerDir + "app_webview");
            file = new File(baseInner + "Cookies");
            ShellUtils.copyFileAndCtx(file, dir);

            // 恢复contentProvider device_id信息
            dir = new File(baseExternalDir + "bytedance");
            file = new File(baseExternal + "device_parameters.dat");
            ShellUtils.copyFile(file, dir);
            file = new File(baseExternal + "persist_data.txt");
            ShellUtils.copyFile(file, dir);
        } else {
            // 恢复SharedPreferences 账户信息
            File dir = new File(baseInnerDir + "shared_prefs");
            file = new File(baseInner + "aweme_user.xml");
            ShellUtils.moveFile(file, dir);
            // 恢复SharedPreferences cdid信息
            file = new File(baseInner + "com.ss.android.deviceregister.utils.Cdid.xml");
            ShellUtils.moveFile(file, dir);
            // 恢复SharedPreferences udid、udid_list、openudid、clientudid、serial_number信息
            file = new File(baseInner + "snssdk_openudid.xml");
            ShellUtils.moveFile(file, dir);
            // 恢复SharedPreferences device_id信息
            file = new File(baseInner + "applog_stats.xml");
            ShellUtils.moveFile(file, dir);
            // 恢复SharedPreferences cookies缓存
            file = new File(baseInner + "ttnetCookieStore.xml");
            ShellUtils.moveFile(file, dir);

            // 恢复Files 下的device信息
            dir = new File(baseInnerDir + "files/keva/");
            file = new File(baseInner + "repo");
            ShellUtils.moveFile(file, dir);
            // 恢复APP_WEBVIEW下cookies缓存
            dir = new File(baseInnerDir + "app_webview");
            file = new File(baseInner + "Cookies");
            ShellUtils.moveFile(file, dir);

            // 恢复contentProvider device_id信息
            dir = new File(baseExternalDir + "bytedance");
            file = new File(baseExternal + "device_parameters.dat");
            ShellUtils.moveFile(file, dir);
            file = new File(baseExternal + "persist_data.txt");
            ShellUtils.moveFile(file, dir);
        }

        TraceUtil.e("****** dy restore app end ******");
    }

}
